/*
 *--------------------------------------------------------------------------
 *   Battlefield - A Realtime Network Multiplayer Game
 *   =======================================================
 *   Developed by Group D02 - 2009/2010 Semester 4 - CS2103
 *     Harry Nguyen Duy Hoang <nnduyhoang@yahoo.co.uk>
 *     Kent Chng Siang Rong <fivefootway@gmail.com>
 *     Lim Yong Peng <limpeng1986@gmail.com>
 *     Loh Xiankun <u0807185@nus.edu.sg>
 *   Instructed by
 *     Dr. Damith C.Rajapakse <damith@gmail.com>
 *   =======================================================
 *   $Id: GameManager.java 630 2010-07-27 15:39:35Z Kent $
 *   $LastChangedDate: 2010-07-27 15:39:35 +0000 (Tue, 27 Jul 2010) $
 *   $LastChangedBy: Kent $
 *--------------------------------------------------------------------------
 */
package battlefield.manager;

import battlefield.BattlefieldException;
import battlefield.entity.*;
import battlefield.state.GamePhase;
import battlefield.state.PlayerState;
import battlefield.util.IDGenerator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Harry Nguyen, Kent
 */
public class GameManager extends HashMap<Integer, Game> {

    private IDGenerator idGenerator;

    /**
     * Constructs a GameManager Object that will manage all games created in this server
     */
    public GameManager() {
        idGenerator = new IDGenerator();
    }

    /**
     * Returns the game object using gameId
     * 
     * @param gameId
     * @return
     * @throws BattlefieldException
     */
    public Game get(int gameId) throws BattlefieldException {
        if (gameId<=0) throw new BattlefieldException("Invalid Game ID.");
        if (super.get(gameId) == null) {
            throw new BattlefieldException("Game not found.");
        }

        return super.get(gameId);
    }

    /**
     * Creates a game object using the client's Player object whenever a client
     * connects to the server to play a game
     * @param player
     * @return Game
     */
    public Game createGame(Player player) {
        Game game = new Game(idGenerator.next());
        game.getPlayers().add(player);
        put(game.getId(), game);
        return game;
    }

    /**
     * Returns a List of all game objects create in this server
     * @return List<Game>
     */
    public List<Game> listGames() {
        return new ArrayList<Game>(values());
    }

    /**
     * Allows a player to join a particular game that is made available on the server
     * 
     * @param game
     * @param player
     * @throws BattlefieldException
     */
    public void joinGame(Game game, Player player) throws BattlefieldException {
        if (game.getPlayers().size() > 2) {
            throw new BattlefieldException("Game is already full.");
        }
        game.getPlayers().add(player);
    }

    /**
     * Sets the setting of a game with the following parameters
     * @param game the game to set the settings in
     * @param goldReloadDuration the duration required before gold is reloaded
     * @param goldReloadAmt the amount of gold to reload
     * @param startGold the amount of gold to start with
     * @throws BattlefieldException
     */
    public void setGameSettings(Game game, int goldReloadDuration, int goldReloadAmt, int startGold) throws BattlefieldException {
        if(goldReloadDuration<=0)throw new BattlefieldException("Reload duration should have negative values");
        if(goldReloadAmt<500)throw new BattlefieldException("Reload amount should have a minimum value of 500");
        if(startGold<=1500)throw new BattlefieldException("Start gold should have a minimum value of 1500");
        game.setGoldReloadDuration(goldReloadDuration);
        game.setGoldReloadAmount(goldReloadAmt);
        game.setStartGold(startGold);
    }

    /**
     * Returns the list of all player currently playing in a game
     * @param game
     * @return List<Player>
     */
    public List<Player> getGamePlayers(Game game) {
        for (Game g : values()) {
            if (g.getId() == game.getId()) {
                return g.getPlayers();
            }
        }
        return game.getPlayers();
    }

    /**
     * Return the game that a particular player is currently playing in
     * @param player
     * @return Game
     */
    public Game getCurrentGame(Player player) {
        for (Game game : values()) {
            if (game.getPlayers().contains(player)) {
                return game;
            }
        }
        return null;
    }

    /**
     * Starts the tactical phase of the game
     * @param game
     * @param player
     * @throws BattlefieldException
     */
    public void startTacticalPhase(Game game, Player player) throws BattlefieldException {
        game.setPhase(GamePhase.TACTICS);
        player.setState(PlayerState.NOT_READY);
    }

    /**
     * Player declaring that the end of player's tactical phase
     * @param player
     * @throws BattlefieldException
     */
    public void endTacticalPhase(Player player) throws BattlefieldException {
        if(player.getMap()==null)
            throw new BattlefieldException("Player map not created");
        if (player.getMap().getUnits().size() <= 0)
            throw new BattlefieldException("Please place at least one unit on the map.");
        player.setState(PlayerState.DONE);
    }

    /**
     * Starts the war phase of the game
     * @param game
     * @throws BattlefieldException
     */
    public void startWarPhase(Game game) throws BattlefieldException {
        if(game==null) throw new BattlefieldException("Null game object provided");
        game.setPhase(GamePhase.WAR);
    }

    /**
     *
     * @param player
     * @return
     */
    public Player getOpponent(Player player) {
        Game game = getCurrentGame(player);
        for (Player player2 : game.getPlayers()) {
            if (!player2.equals(player)) {
                return player2;
            }
        }
        return null;
    }

    /**
     *
     * @param player
     * @return
     */
    public boolean isGameHost(Player player) {
        Game game = getCurrentGame(player);
        if (game != null && game.getPlayers().size() > 0 && game.getPlayers().get(0).equals(player)) {
            return true;
        }
        return false;
    }
}
